package com.association.interceptor;

import com.alibaba.fastjson.JSON;
import com.association.constant.CacheConstant;
import com.association.model.vo.CourierTokenBean;
import com.association.service.UserService;
import com.association.utils.RequestTokenBeanLocal;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.exceptions.JedisException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by tuli on 2020/4/21.
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
    Logger log = LoggerFactory.getLogger(TokenInterceptor.class);
    /**
     * 服务器间验证令牌传递信息头KEY
     */
	public static final String TOKEN_HEADER_KEY = "TOKEN";

    private static final String TRACE_ID = "TRACE_ID";

    public static boolean CHECK_TOKEN = true;


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                Exception exception) throws Exception {
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        MDC.remove(TRACE_ID);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String token = request.getHeader(TOKEN_HEADER_KEY);
        Map<String, Object> map = new HashMap<String, Object>();

        if (!StringUtils.isEmpty(token)) {

            try {
                if (CHECK_TOKEN == false || validateToken(token, request)) {
                    putTarceId(token, request);
                    return true;
                } else {
                    map.put("code", 405);
                    map.put("message", String.format("本次登录已超%s天，请重新登录后再操作！", "1"));
                    out(response, map);
                    return false;
                }
            } catch (JedisException je){
                je.printStackTrace();
                map.put("code", 405);
                map.put("message", "用户信息获取异常，请稍后再操作！");
                out(response, map);
                return false;
            }catch (Exception e) {
                e.printStackTrace();
                map.put("code", 405);
                map.put("message", "token校验异常，请重新登录后再操作！");
                out(response, map);
                return false;
            }
        } else {
            map.put("code", 405);
            map.put("message", "缺少身份验证信息！请重新登录后再操作！");
            out(response, map);
            return false;
        }
    }

    private void out(HttpServletResponse response, Map<String, Object> map) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println(JSON.toJSONString(map));
        out.flush();
        out.close();
    }

    /**
     * @param strToken
     * @param request
     * @return
     * @throws Exception
     */
    private boolean validateToken(String strToken, HttpServletRequest request) throws Exception {
        boolean validated = false;
        if (!StringUtils.isEmpty(strToken)) {
            CourierTokenBean tokenBean = JSON.parseObject(buildCacheKey(CacheConstant.TOKEN_KEY_PREFIX,strToken),CourierTokenBean.class);
            if (tokenBean != null) {
                if (!StringUtils.isEmpty(tokenBean.getUserCode())) {
                    RequestTokenBeanLocal.set(tokenBean);
                    validated = true;
                } else {
                    log.error(String.format("=============== 非法请求，盗用token，或操作其他网点数据 header token:%s,requestID:%s,url:%s",
                            JSON.toJSONString(tokenBean), request.getHeader("requestID"), request.getRequestURI()));
                }
            }
        }
        return validated;
    }
    public static String buildCacheKey(String cacheKey, Object... values) {
        return String.format(cacheKey, values);
    }
    private void putTarceId(String token, HttpServletRequest request){
        String value = token + String.valueOf(System.currentTimeMillis()).substring(6);
        String id = value +"/" + request.getHeader("deviceNo")+ "/" + request.getHeader("deviceType") + "/" + request.getHeader("appVersionNo");
        MDC.put(TRACE_ID, id);
    }
}
